package com.vietnam.power.service.impl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.vietnam.power.constant.AppConfigurationConstant;
import com.vietnam.power.dao.ApplicationDao;
import com.vietnam.power.dao.ArticleDao;
import com.vietnam.power.domain.Article;
import com.vietnam.power.domain.ArticleGroup;
import com.vietnam.power.domain.ArticleSearchCriteria;
import com.vietnam.power.persitence.ArticleImage;
import com.vietnam.power.persitence.FileUpload;
import com.vietnam.power.service.ArticleService;
import com.vietnam.power.service.FileService;

@Service
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
public class ArticleServiceImpl implements ArticleService {

	@Autowired
	private ArticleDao articleDao;

	@Autowired
	private ApplicationDao applicationDao;

	@Autowired
	private FileService fileService;

	public Article getArticleById(int id) {
		return convertoArticleDomain(articleDao.getArticleById(id));
	}

	public List<Article> getArticleListByGroupName(ArticleSearchCriteria asc, Integer page) {
		if (page == null) {
			page = 1;
		}

		int max = applicationDao.getAppConfigurationByName(AppConfigurationConstant.APP_CONFIGURATION.MAX_ARTICLES_PER_PAGE).getThreshold();
		int totalProduct = articleDao.totalArticles(asc);
		long totalPage = (long) Math.ceil(totalProduct / (double) max);

		List<Article> lst = new ArrayList<Article>();
		for (com.vietnam.power.persitence.Article art : articleDao.getArticleListByCriteria(asc, page, max)) {
			Article a = convertoArticleDomain(art);
			a.setTotalPage(totalPage);

			lst.add(a);
		}
		return lst;
	}

	private Article convertoArticleDomain(com.vietnam.power.persitence.Article art) {
		Article a = new Article();
		a.convertToDomain(art);

		return a;
	}

	public ArticleGroup getArticleGroup(int id) {
		ArticleGroup ag = new ArticleGroup();
		ag.convertToDomain(articleDao.getArticleGroup(id));

		return ag;
	}

	public void createArticleGroup(ArticleGroup ag) {
		com.vietnam.power.persitence.ArticleGroup pag = new com.vietnam.power.persitence.ArticleGroup();
		ag.convertToPersist(pag);
		articleDao.createArticleGroup(pag);

	}

	public void updateArticleGroup(ArticleGroup ag) {
		com.vietnam.power.persitence.ArticleGroup pag = articleDao.getArticleGroup(ag.getId());
		ag.convertToPersist(pag);

		articleDao.updateArticleGroup(pag);
	}

	public void deleteArticleGroup(int id) {
		com.vietnam.power.persitence.ArticleGroup pag = articleDao.getArticleGroup(id);

		articleDao.deleteArticleGroup(pag);
	}

	public void createArticle(Article a) {
		com.vietnam.power.persitence.Article pa = new com.vietnam.power.persitence.Article();
		a.convertToPersist(pa);

		for (Integer i : a.getArticleImages()) {
			ArticleImage ai = new ArticleImage();
			ai.setFileUpload(new FileUpload(i));
			ai.setArticle(pa);

			pa.addArticleImage(ai);
			fileService.updateFileStatusToActive(i,null);
		}

		articleDao.createArticle(pa);

		a.setId(pa.getId());
	}

	public List<Integer> updateArticle(Article a) {
		com.vietnam.power.persitence.Article pa = articleDao.getArticleById(a.getId());
		a.convertToPersist(pa);

		List<Integer> deletedFileIds = new ArrayList<Integer>();
		Iterator<ArticleImage> itr = pa.getArticleImages().iterator();

		while (itr.hasNext()) {
			ArticleImage i = itr.next();
			if (a.getArticleImages().contains(i.getFileUpload().getId())) {
				a.getArticleImages().remove(Integer.valueOf(i.getFileUpload().getId()));
			} else {
				deletedFileIds.add(i.getFileUpload().getId());
				itr.remove();
			}
		}

		for (Integer i : a.getArticleImages()) {
			ArticleImage pi = new ArticleImage();
			pi.setFileUpload(new FileUpload(i));
			pi.setArticle(pa);

			pa.addArticleImage(pi);
			fileService.updateFileStatusToActive(i,null);
		}

		articleDao.updateArticle(pa);
		// delete files too
		return deletedFileIds;
	}

	public List<Integer> deleteArticle(int id) {
		com.vietnam.power.persitence.Article pa = articleDao.getArticleById(id);
		articleDao.deleteArticle(pa);
		List<Integer> deletedFileIds = new ArrayList<Integer>();
		// delete image file here
		for (ArticleImage pi : pa.getArticleImages()) {
			deletedFileIds.add(pi.getFileUpload().getId());
		}

		return deletedFileIds;
	}

	public List<Article> searchArticle(ArticleSearchCriteria asc) {
		List<Article> lst = new ArrayList<Article>();
		for (com.vietnam.power.persitence.Article art : articleDao.searchArticle(asc)) {
			Article a = convertoArticleDomain(art);
			lst.add(a);
		}
		return lst;
	}

	public List<ArticleGroup> getArticleGroupList() {
		List<ArticleGroup> lst = new ArrayList<ArticleGroup>();

		for (com.vietnam.power.persitence.ArticleGroup pg : articleDao.getArticleGroupList()) {
			ArticleGroup ag = new ArticleGroup();
			ag.convertToDomain(pg);
			lst.add(ag);
		}

		return lst;
	}
	
	public boolean validateArticlesInGroup(int groupId){
		long no =  articleDao.countArticleNumberInGroup(groupId);
		
		ArticleGroup ag = getArticleGroup(groupId);
		
		if (StringUtils.equalsIgnoreCase(ag.getName(), AppConfigurationConstant.ARTICLE_GROUP.ABOUT_US)) {
			int max = applicationDao.getAppConfigurationByName(AppConfigurationConstant.APP_CONFIGURATION.MAX_ARTICLES_FOR_ABOUT_US).getThreshold();
			if (no >= max) {
				return false;
			}
		}
		
		if (StringUtils.equalsIgnoreCase(ag.getName(), AppConfigurationConstant.ARTICLE_GROUP.CONTACT)) {
			int max = applicationDao.getAppConfigurationByName(AppConfigurationConstant.APP_CONFIGURATION.MAX_ARTICLES_FOR_CONTACT_US).getThreshold();
			if (no >= max) {
				return false;
			}
		}
		
		return true;
	}

}
